/*
 * AplEmitirCertificado.java
 * 
 * Projeto: Kruskal - SRAC
 * LEDS - Laboratório de Engenharia e Desenvolvimento de Software
 * IFES - Instituto Federal do Espírito Santo - Campus Serra.
 */
package srac.controleeventos.cgt;

import com.lowagie.text.BadElementException;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import java.io.*;
import java.net.MalformedURLException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.mail.EmailException;
import srac.controleatividades.cdp.Aluno;
import srac.controleatividades.cgt.AplCadastroInterno;
import srac.controleeventos.cdp.Certificado;
import srac.controleeventos.cdp.Evento;
import srac.controleeventos.cdp.Participante;
import util.utilitarioMail.Mail;
import util.utilitarioPDF.Converte;
import util.utilitarioPersistencia.DAO;
import util.utilitarioPersistencia.DAOFactory;

public class AplEnviarCertificado {

    static private AplEnviarCertificado instance = null;

    static public AplEnviarCertificado getInstance() {
        if (instance == null) {
            instance = new AplEnviarCertificado();
        }
        return instance;
    }
    
    public static void enviarCertificado(Certificado certificado) throws EmailException, MalformedURLException, FileNotFoundException, IOException {
        File f = Converte.converteByteArrayparaPDF(certificado.getArquivo(), "Certificado");
        HashMap emailInfo = new HashMap();
        
        emailInfo.put(Mail.DESCRICAO_ANEXO, "Certificado do Evento - " + certificado.getEvento().getNome());
        emailInfo.put(Mail.END_DESTINATARIO, certificado.getParticipante().getEmail());
        emailInfo.put(Mail.NOME_DESTINATARIO, certificado.getParticipante().getNome());
        emailInfo.put(Mail.ASSUNTO, "Certificado do Evento - " + certificado.getEvento().getNome());
        emailInfo.put(Mail.CONTEUDO, String.format("Segue em anexo o certificado do evento %s.", certificado.getEvento().getNome()));
        emailInfo.put(Mail.ASSINATURA, "Coordenadoria de Informática");
        
        Mail.getInstance().enviarEmailComAnexo(emailInfo, f);
        
        f.deleteOnExit();
        
    }
    
    /**
     * Gera um arquivo pdf a partir de um Template.
     * @param participante
     * @param certificado
     * @throws FileNotFoundException
     * @throws IOException
     * @throws DocumentException
     * @throws NoSuchAlgorithmException 
     */
    public static void gerarPdf(Certificado certificado) throws FileNotFoundException, IOException, DocumentException, NoSuchAlgorithmException, EmailException{
        AplCadastroInterno aplInterno = AplCadastroInterno.getInstance();
        AplControleEvento aplEvento = AplControleEvento.getInstance();
        
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        
        //Properties prop = certificado.retrieveProperties();
          
        Properties prop = new Properties();
        prop.load(AplEnviarCertificado.class.getClassLoader().getResourceAsStream("/certificado.properties")); // loading das propriedades do certificado
        
        //Properties prop = new Properties();
        //prop.load(new FileInputStream("certificado/certificado.properties")); // loading das propriedades do certificado
          
        // inicia variaveis 
        Formatter formatter;
        Evento evento = certificado.getEvento();
        String matOuCpf;
        String tipoEvento = abreviaTipoEvento(evento.getTipo().getDescricao());
        String nomeEvento = evento.getNome();
        String localEvento = String.format("%s, %d, %s, %s, %s - %s", evento.getEndereco().getLogradouro(), 
                                                                      evento.getEndereco().getNumero(), 
                                                                      evento.getEndereco().getComplemento(), 
                                                                      evento.getEndereco().getBairro().getNome(),
                                                                      evento.getEndereco().getBairro().getMunicipio().getNome(), 
                                                                      evento.getEndereco().getBairro().getMunicipio().getEstado().getSigla());
        formatter = new Formatter();
        String dataEvento = formatter.format("%1$te de %tB de %1$tY", evento.getData()).toString();
        formatter.close();
        formatter = new Formatter();
        String dataCertificado = formatter.format("%1$te de %tB de %1$tY", GregorianCalendar.getInstance().getTime()).toString();
        formatter.close();
        String codigoCertificado;
        
        //TODO melhorar a maneira como acha o participante na lista de aluno, se tiver 2 com o mesmo nome? ex:Jose da Silva
        List <Aluno> listaAluno = (List <Aluno>) aplInterno.obterAluno(certificado.getParticipante().getNome());
        
        PdfReader pdfTemplate = new PdfReader(AplEnviarCertificado.class.getClassLoader().getResourceAsStream("/"+prop.getProperty("template")));// loading do Template em PDF usando formulario
        
        //PdfReader pdfTemplate = new PdfReader(AplEnviarCertificado.class.getClassLoader().getResourceAsStream("/TemplateCertificadov2.2.pdf"));// loading do Template em PDF usando formulario
        
        PdfStamper stamper = new PdfStamper(pdfTemplate, output);
        stamper.setFormFlattening(true);
        stamper.getAcroFields().setField("dataCertificado", dataCertificado +".");
        stamper.getAcroFields().setField("nomeGerente", prop.getProperty("nomeGerente"));
        stamper.getAcroFields().setField("nomeCoordenador", prop.getProperty("nomeCoordenador"));
        //stamper.getAcroFields().setField("descricaoCertificado", "CONTEUDO do EVENTO, descrições etc\n continua \n");// quando tiver descrição ou conteudo do evento usar aqui
        
        if(!listaAluno.isEmpty()){
            Aluno a=null;
            if(listaAluno.size() > 1){// se tiver alunos com o mesmo nome
                for (int i = 0; i < listaAluno.size(); i++) {// abaixo compara se tem o mesmo cpf caso sim atribui aluno a a, senao valor de a continua sendo a
                    a = (listaAluno.get(i).getCpf() == null ? certificado.getParticipante().getCpf() == null : listaAluno.get(i).getCpf().equals(certificado.getParticipante().getCpf())) ? listaAluno.get(i) : a;
                }
                
            }
            else{
                a = listaAluno.get(0);// se nao pega apenas o primeiro e unico da lista
            }
            
            matOuCpf = a.getMatricula();
            stamper.getAcroFields().setField("corpoCertificado", String.format("Certificamos que o aluno %s - matrícula %s participou do EVENTO: %s - \"%s\" realizado no %s, no dia %s.", certificado.getParticipante().getNome().toUpperCase(), a.getMatricula().toUpperCase(), tipoEvento.toUpperCase(), nomeEvento, localEvento, dataEvento));
                                
            }
        
         else{
            matOuCpf = certificado.getParticipante().getCpf();
            stamper.getAcroFields().setField("corpoCertificado", String.format("Certificamos que %s participou do EVENTO: %s - \"%s\" realizado no %s, no dia %s.", certificado.getParticipante().getNome().toUpperCase(), tipoEvento.toUpperCase(), nomeEvento, localEvento, dataEvento));
         }
            
            // gera o codigo do certificado a partir do arquivo de template id do evento e matricula
            codigoCertificado = Certificado.gerarCodigoCertificado(output.toByteArray(), evento.getId().toString(), matOuCpf);
            stamper.getAcroFields().setField("codigoCertificado", codigoCertificado);
            
            // necessário fechar antes de salvar o arquivo, caso contrário o arquivo fica corrompido
            pdfTemplate.close();//fecha template
            stamper.close();//fecha stamper
            
            // salva o sertificado criado
            certificado.setCodigo(codigoCertificado);// set codigo
            certificado.setArquivo(output.toByteArray());//set arquivo
            
            // reseta o output para ser utlizado novamente durante iteracao
            output.reset();
            output.close();// fecha o output
            
            //TODO mudar, não é o melhor lugar para chamar essa função
            AplEnviarCertificado.enviarCertificado(certificado);
    }
    
    
//    /**
//     * @deprecated 
//     * @param listaParticipantes
//     * @param evento
//     * @throws BadElementException
//     * @throws MalformedURLException
//     * @throws IOException
//     * @throws DocumentException
//     * @throws Exception 
//     */
//    public static void gerarPdf(List<Participante> listaParticipantes, Evento evento) throws BadElementException, MalformedURLException, IOException, DocumentException, Exception {
//        
//        AplCadastroInterno aplInterno = AplCadastroInterno.getInstance();
//        AplControleEvento aplEvento = AplControleEvento.getInstance();
//        DAO apDaoCertificado = DAOFactory.obterDAO(Certificado.class);
//        
//        ByteArrayOutputStream output = new ByteArrayOutputStream();
//        Properties prop = new Properties();
//        
//        prop.load(new FileInputStream("certificado/certificado.properties")); // loading das propriedades do certificado
//        
//		
//        
//        // inicia variaveis 
//        Formatter formatter;
//        String matOuCpf;
//        String tipoEvento = abreviaTipoEvento(evento.getTipo().getDescricao());
//        String nomeEvento = evento.getNome();
//        String localEvento = String.format("%s, %d, %s, %s, %s - %s", evento.getEndereco().getLogradouro(), 
//                                                                      evento.getEndereco().getNumero(), 
//                                                                      evento.getEndereco().getComplemento(), 
//                                                                      evento.getEndereco().getBairro().getNome(),
//                                                                      evento.getEndereco().getBairro().getMunicipio().getNome(), 
//                                                                      evento.getEndereco().getBairro().getMunicipio().getEstado().getSigla());
//        formatter = new Formatter();
//        String dataEvento = formatter.format("%1$te de %tB de %1$tY", evento.getData()).toString();
//        formatter.close();
//        formatter = new Formatter();
//        String dataCertificado = formatter.format("%1$te de %tB de %1$tY", GregorianCalendar.getInstance().getTime()).toString();
//        formatter.close();
//        String codigoCertificado;
//        
//        
//        for(Participante participante: listaParticipantes){
//            
//            List <Aluno> listaAluno = (List <Aluno>) aplInterno.obterAluno(participante.getNome());
//            PdfReader pdfTemplate = new PdfReader("certificado/TemplateCertificadov2.0.pdf");// loading do Template em PDF usando formulario
//            PdfStamper stamper = new PdfStamper(pdfTemplate, output);
//            stamper.setFormFlattening(true);
//            stamper.getAcroFields().setField("dataCertificado", dataCertificado +".");
//            stamper.getAcroFields().setField("nomeGerente", prop.getProperty("nomeCoordenador"));
//            stamper.getAcroFields().setField("nomeCoordenador", prop.getProperty("nomeCoordenador"));
//
//            
//            if(!listaAluno.isEmpty()){
//                Aluno a = listaAluno.get(0);
//                matOuCpf = a.getMatricula();
//                stamper.getAcroFields().setField("corpoCertificado", String.format("Certificamos que o aluno %s - matrícula %s participou do EVENTO: %s: \"%s\" realizado no %s, no dia %s.", participante.getNome().toUpperCase(), a.getMatricula().toUpperCase(), tipoEvento.toUpperCase(), nomeEvento, localEvento, dataEvento));
//                //stamper.getAcroFields().setField("descricaoCertificado", "CONTEUDO do EVENTO, descrições etc\n continua \n");
//                
//            }
//            else{
//                matOuCpf = participante.getCpf();
//                stamper.getAcroFields().setField("corpoCertificado", String.format("Certificamos que %s participou do EVENTO: %s: \"%s\" realizado no %s, no dia %s.", participante.getNome().toUpperCase(), tipoEvento.toUpperCase(), nomeEvento, localEvento, dataEvento));
//            }
//            
//            // gera o codigo do certificado a partir do arquivo de template id do evento e matricula
//            codigoCertificado = Certificado.gerarCodigoCertificado(output.toByteArray(), evento.getId().toString(), matOuCpf);
//            stamper.getAcroFields().setField("codigoCertificado", codigoCertificado);
//            
//            // necessário fechar antes de salvar o arquivo, caso contrário o arquivo fica corrompido
//            pdfTemplate.close();//fecha template
//            stamper.close();//fecha stamper
//            
//            // salva o sertificado criado
//            Certificado certificado = new Certificado();// cria novo certificado
//            certificado.setParticipante(participante); //set participante
//            certificado.setEvento(evento);// set evento
//            certificado.setCodigo(codigoCertificado);// set codigo
//            certificado.setArquivo(output.toByteArray());//set arquivo
//            
//            //salva o Certificado no banco de dados
//            apDaoCertificado.salvar(certificado);
//            
//            // reseta o output para ser utlizado novamente durante iteracao
//            output.reset();
//        }
//        
//        
//        output.close();// fecha o output
//    }
    
    /**
     * Identificada através de uma expressão regular o tipo de evento e abrevia a string se ela for maior que 27
     * @param tipoEvento
     * @return 
     */
    private static String abreviaTipoEvento(String tipoEvento){
        String abreviacao = "";
        
        if(tipoEvento.length()>27){
            
            if(tipoEvento.matches("(?is).*(palestra).*")){// se for palestra
                abreviacao = "Palestra";
            }
            
            if(tipoEvento.matches("(?is).*(curso).*")){// se for curso
                abreviacao = "Curso";
            }
            
            else{
            
            String [] partes = tipoEvento.split("(?is)(\\s)");// separa a string em partes
            abreviacao = String.format("%s ", partes[0]);
            for (int i = 1; i < partes.length; i++) {
                
                if(!partes[i].matches("(?is)(de|o|a|em|com|um|uma)")){// se nao for artigos ou preporsições
                abreviacao = abreviacao + String.format("%c", partes[i].charAt(0)).toUpperCase();//pega a primeira letra em caixa alta e concatena ex: defesa de "TCC"
                }
                else if(i==1){
                    abreviacao = abreviacao + String.format("%s ", partes[i]);// concatena pelo menos uma palavra de ligacao (artigo ou preposicao) ex: defesa "de" TCC
                }
            }
            
            
            }
            
        }
        else{
            return tipoEvento;
        }
        return abreviacao;
    }
/*   
    public static void main (String[] args){
        AplCadastroInterno apl = AplCadastroInterno.getInstance();
        AplControleEvento aple = AplControleEvento.getInstance();
        AplEnviarCertificado aplc = AplEnviarCertificado.getInstance();
        
        
        try {
            
            List<Participante> ps = aple.obterEventoParticipante(aple.obterEvento().get(0));
            
            if(!ps.isEmpty()){
                for (int i = 0; i < ps.size(); i++) {
                    Participante participante = ps.get(i);
                    List<Certificado> cs = aple.obterCertificados(participante);
                    //aplc.emitirCertificados(ps);
               
                    if(!cs.isEmpty()){
                        for (int j = 0; j < cs.size(); j++) {
                            Certificado certificado = cs.get(j);
                             aplc.enviarCertificado(certificado);
                          
                        }
                    }
                }
            }
            
            
        }
        catch (Exception ex) {
            Logger.getLogger(AplEnviarCertificado.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
 //*/ 

    public void emitirCertificados(List<Participante> participantes) {
        
    }
}
